const auth = require("../../utils/auth.js");
const response = require("../../utils/response.js");
const validate = require("../../utils/validate.js");
const userService = require("../services/userService.js");
const bcrypt = require('bcryptjs');
const { URLSearchParams } = require('url');
const { createUserRules, deleteUserRules, loginUserRules, updateUserRules, updateMyPasswordRules, getUserByIdRules, getVerificationCodeRules, retrieveUserPasswordRules, updateUserVideoIndexRules, updateUserVideoPageRules } = require("../validations/userValidation.js");
const sequelize = require("../db/index.js");
const { sendMail } = require("../../utils/email.js");
const Jwt = require('jsonwebtoken');

class UserController {
    async addUser(ctx) {
        const t = await sequelize.transaction();
        try {
            const userData = await validate(ctx, createUserRules);

            const existingEmail = await userService.getUserByEmail(userData.email, t);
            if (existingEmail) {
                return response.error(ctx, '该邮箱已注册');
            }

            // 校验验证码
            try{
                const decoded = Jwt.verify(userData.uuid, process.env.JTW_SECRET);
                if(!decoded) throw '请重新获取验证码'
                if(decoded.verificationCode != userData.verificationCode) throw '验证码错误'
            }catch(err){
                throw '验证码失效'
            }

            let inviter;
            if(userData.inviteId){
                // 如果有邀请人则为邀请人添加3天vip
                inviter = await userService.getUserById(userData.inviteId, t);
                if(!inviter) throw '邀请人不存在'

                let time = inviter.dataValues.membershipExpireAt ? new Date(inviter.dataValues.membershipExpireAt).getTime() : Date.now()
                inviter.setDataValue('membershipExpireAt', time + 3 * 24 * 60 *60 * 1000);
                await inviter.save({
                    transaction: t
                });
            }

            // 添加用户
            userData.password = await bcrypt.hash(userData.password, 10);
            const { id } = await userService.addUser(userData, t);

            await t.commit();
            response.success(ctx, id, '注册成功');

            // 发送邮件通知
            if(inviter){
                await sendMail('企鹅视频: 邀请成功', `您已成功邀请一位好友, 已赠送您3天vip~`, inviter.dataValues.email);
            }
            await sendMail('企鹅视频: 注册成功', `您已注册成功~`, userData.email);
        } catch (err) {
            await t.rollback();
            console.log(err)
            response.error(ctx, err);
        }
    }
    // 获取验证码
    async getVerificationCode(ctx){
        try{
            const { email } = await validate(ctx, getVerificationCodeRules);
            const verificationCode =  Math.floor(Math.random() * 100000 + 100000);

            const expireMinute = 5;
            await sendMail('企鹅视频', `您的验证码是${verificationCode}, 有效期为${expireMinute}分钟, 不要随便告诉别人噢~`, email);

            const token = Jwt.sign({ verificationCode }, process.env.JTW_SECRET, { expiresIn: expireMinute + 'm' });
            response.success(ctx, token);
        }catch(err){
            console.log(err)
            response.error(ctx, err);
        }
    } 
    // 找回密码
    async retrieveUserPassword(ctx){
        try {
            const userData = await validate(ctx, retrieveUserPasswordRules);

            const existingEmail = await userService.getUserByEmail(userData.email);
            if (!existingEmail) {
                return response.error(ctx, '该邮箱未注册');
            }

            // 校验验证码
            const decoded = Jwt.verify(userData.uuid, process.env.JTW_SECRET);
            if(!decoded) throw '请重新获取验证码'
            if(decoded.verificationCode != userData.verificationCode) throw '验证码错误'

            userData.newPassword = await bcrypt.hash(userData.newPassword, 10);
            existingEmail.setDataValue('password', userData.newPassword);
            await existingEmail.save();

            response.success(ctx, existingEmail.dataValues.id, '修改稿成功');
        } catch (err) {
            console.log(err)
            response.error(ctx, err);
        }
    }
    async deleteUser(ctx) {
        try {
            const userData = await validate(ctx, deleteUserRules);

            const affectedRows = await userService.deleteUser(userData.id);
            if (affectedRows > 0) {
                response.success(ctx, userData.id, '删除成功')
            } else {
                response.error(ctx, '删除失败')
            }
        } catch (err) {
            console.log(err)
            response.error(ctx, err);
        }
    }
    async updateUser(ctx) {
        try {
            const userData = await validate(ctx, updateUserRules);

            if (userData.password) {
                userData.password = await bcrypt.hash(userData.password, 10);
            }
            const affectedRows = await userService.updateUser(userData);
            if (affectedRows > 0) {
                response.success(ctx, '修改成功')
            } else {
                response.error(ctx, '修改失败')
            }
        } catch (err) {
            console.log(err)
            response.error(ctx, err);
        }
    }
    async loginUser(ctx) {
        try {
            const userData = await validate(ctx, loginUserRules);

            const row = await userService.getUserByEmail(userData.email);

            if (!row) {
                return response.error(ctx, '用户名或密码错误');
            }
            const passwordMatch = await bcrypt.compare(userData.password, row.password);
            if (!passwordMatch) {
                return response.error(ctx, '用户名或密码错误');
            }
            const authData = auth.sing({
                data: row,
                role: 'user'
            })
            delete row.dataValues.password;
            response.success(ctx, {
                userInfo: row,
                ...authData
            });

        } catch (err) {
            console.log(err)
            response.error(ctx, err);
        }
    }
    async userInfo(ctx) {
        if (ctx.state.user) {
            const userInstance = await userService.getUserById(ctx.state.user.id);
            return response.success(ctx, userInstance)
        } else {
            return response.error(ctx, "登录状态已过期", null, 401)
        }
    }
    async getUserListByPage(ctx) {
        const usp = new URLSearchParams(ctx.querystring);
        let page = Number(usp.get('page')) || 1;
        let limit = Number(usp.get('limit')) || 10;
        let keyword = usp.get('keyword') || '';
        try {
            const { rows, count } = await userService.getUserListByPage(page, limit, keyword);
            response.success(ctx, {
                page,
                limit,
                rows,
                total: count
            });
        } catch (err) {
            console.log(err, 'getUserListByPage')
            response.error(ctx, err);
        }
    }
    async userLogout(ctx) {
        if (ctx.state.user) {
            return response.success(ctx, null)
        } else {
            return response.error(ctx, "登录状态已过期", null, 401)
        }
    }
    async updateMyPassword(ctx) {
        try {
            if (!ctx.state.user) {
                return response.error(ctx, "登录状态已过期", null, 401)
            }

            const userData = await validate(ctx, updateMyPasswordRules);
            console.log(userData.newPassword, ctx.state.user.password)
            const passwordMatch = await bcrypt.compare(userData.newPassword, ctx.state.user.password);
            if (!passwordMatch) {
                return response.error(ctx, '旧密码错误');
            }

            const affectedRows = await userService.updateUser({
                id: ctx.state.user.id,
                password: await bcrypt.hash(userData.newPassword, 10)
            });
            if (affectedRows > 0) {
                response.success(ctx, null, '修改成功');
            } else {
                response.error(ctx, '修改失败');
            }
        } catch (err) {
            console.log(err)
            response.error(ctx, err);
        }
    }
    async getUserById(ctx){
        try{
            const { id } = await validate(ctx, getUserByIdRules);
            const userData = await userService.getUserById(id);
            if(!userData) throw '没找到对应记录';
            userData.dataValues.password = null
            response.success(ctx, userData);
        }catch(err){
            console.log(err, 'getUserById');
            response.error(ctx, err);
        }
    }
}


module.exports = new UserController();